#include "Chromosome.hpp"
#include <iostream>
namespace synteny {
Node::Node(int gene, int chromosomeID) : gene(gene), sign(PLUS), chromosomeID(chromosomeID)
, nextModifiedPath(0), previousModifiedPath(0)
, nextOriginalPath(0), previousOriginalPath(0)
, hashTableIterator(0)
, modificationState(NotModified) {
	signChanged = false;
}

std::list<Node>::iterator Node::getHeadAdjacent() {
	if (sign == PLUS) {
		return nextModifiedPath;
	}
	else {
		return previousModifiedPath;
	}
}
std::list<Node>::iterator Node::getTailAdjacent() {
	if (sign == PLUS) {
		return previousModifiedPath;
	}
	else {
		return nextModifiedPath;
	}
}
void Node::changeSign() {
	if (sign == PLUS) {
		sign = MINUS;
	}
	else {
		sign = PLUS;
	}
	signChanged = true;
}

Chromosome::Chromosome(int chromosomeID) : chromosomeID(chromosomeID) {
	chromosome.push_back(Node(BEGIN_TERMINAL, chromosomeID));
	chromosome.push_back(Node(END_TERMINAL, chromosomeID));
	NodesList::iterator BTIt(chromosome.begin());
	NodesList::iterator ETIt(--chromosome.end());
	BTIt->nextModifiedPath = ETIt;
	BTIt->nextOriginalPath = ETIt;
	ETIt->previousModifiedPath = BTIt;
	ETIt->previousOriginalPath = BTIt;
}
NodesList::iterator Chromosome::tailInsertNode(int gene) {
	NodesList::iterator ETIt(--chromosome.end());
	NodesList::iterator pOIt(ETIt->previousOriginalPath);
	NodesList::iterator pMIt(ETIt->previousModifiedPath);
	NodesList::iterator cIt(chromosome.insert(ETIt, Node(gene, chromosomeID)));
	cIt->nextModifiedPath = ETIt;
	cIt->nextOriginalPath = ETIt;
	cIt->previousModifiedPath = pMIt;
	cIt->previousOriginalPath = pOIt;
	ETIt->previousModifiedPath = cIt;
	ETIt->previousOriginalPath = cIt;
	pOIt->nextOriginalPath = cIt;
	pMIt->nextModifiedPath = cIt;
	return cIt;
}
NodesList::iterator Chromosome::insertNode(NodesList::iterator nIt, int gene) {
	if(nIt->gene != BEGIN_TERMINAL && nIt->modificationState
	!= ChromosomeNode::ModifiedOriginalPath) {
		NodesList::iterator pIt(nIt->previousModifiedPath);
		NodesList::iterator cIt(chromosome.insert(nIt, ChromosomeNode(gene, chromosomeID)));
		cIt->nextModifiedPath = nIt;
		cIt->previousModifiedPath = pIt;
		cIt->modificationState = ChromosomeNode::ModifiedModifiedPath;
		pIt->nextModifiedPath = nIt->previousModifiedPath = cIt;
		return cIt;
	}
	else {
		// throw("Node insertion don't allowed here!");
		std::cerr << "Node insertion don't allowed here!" << std::endl;
		std::cout << "Node insertion don't allowed here!" << std::endl;
		return nIt;
	}
}
NodesList::iterator Chromosome::eraseNode(NodesList::iterator cIt) {
	if(cIt->modificationState != ChromosomeNode::ModifiedOriginalPath
	&& cIt->gene != BEGIN_TERMINAL && cIt->gene != END_TERMINAL) {
		NodesList::iterator pIt(cIt->previousModifiedPath);
		NodesList::iterator nIt(cIt->nextModifiedPath);
		pIt->nextModifiedPath = nIt;
		nIt->previousModifiedPath = pIt;
		switch(cIt->modificationState) {
		case ChromosomeNode::NotModified :
			cIt->previousModifiedPath = chromosome.begin();
			cIt->nextModifiedPath = chromosome.end();
			cIt->modificationState = ChromosomeNode::ModifiedOriginalPath;
			break;
		case ChromosomeNode::ModifiedModifiedPath :
//! Potential ERROR !
//			chromosome.erase(cIt);
			break;
		default :
			// throw("Node deletion wrong behavior!");
			std::cerr << "Node deletion wrong behavior!" << std::endl;
			break;
		}
		return nIt;
	}
	else {
		// throw("Node deletion don't allowed here!");
		std::cerr << "Node deletion don't allowed here!" << std::endl;
		std::cout << "Node deletion don't allowed here!" << std::endl;
		return cIt;
	}
}
}
